package com.asa.control_theory.utils;

import java.util.Arrays;
import java.util.Comparator;
import java.util.Map;

import com.asa.HanShu;
import com.asa.control_theory.utils.bean.ZhuangTai_ZhuanYi_Matrix;
import com.asa.hutils.MathHUtils;
import com.asa.hutils.NTT2My;
import com.asa.hutils.Ni;
import com.asa.numanaly.F;
import com.asa.utils.MathUtils;

/**
 *	 状态转移矩阵
 *	eAt的另外一种计算方法，这种相对于A.java而言，这里是算出函数的方式，而A.java中是用迭代的方式来做
 *
 *	暂时没有支持处理重根
 *(既不支持重根，又没有支持复数域，这让人很难支持。。。但是最少是还是把教科书上的东西完成了)
 *	拉普拉斯变换
 */
public class GongShi4 {
	

	
	public static void main(String[] args) throws Exception {
		
//		double[][] a1 = {{0,1},
//				{-2,-3}};
//		double[][] a1 = {{0,1},
//				{0,-2}};
		
//		create_zhuangtaizhuanyi_matrix_eAt(a1);
		
//		Hamilton_eAt_creatematrix(a1);
		
		
		
		
		
		double[][] a1 = {{0,1,0},
		{0,0,1},
		{1,-3,3}
		};
		create_zhuangtaizhuanyi_matrix_eAt_bytezhengzhi(a1);
		
		
	}

	/**
	 * 通过 Cayley-Hamilton定理方法，生成状态转移矩阵
	 * @param a1
	 * @return
	 */
	public static ZhuangTai_ZhuanYi_Matrix Hamilton_eAt_creatematrix(double[][] a1) {
		double[] juzhengtezhengzhi = MathHUtils.juzhengtezhengzhi(a1);
//		Arrays.sort(juzhengtezhengzhi);
		double[][][] hamilton_eAt = Hamilton_eAt(a1,juzhengtezhengzhi);
		
		
		return create_ztzym(hamilton_eAt, juzhengtezhengzhi);
	}


	/**
	 * 	状态转移矩阵，暂时没有做重根的情况
	 * @param a
	 * @return
	 */
	public static ZhuangTai_ZhuanYi_Matrix create_zhuangtaizhuanyi_matrix_eAt(double[][] a) {
		double[] juzhengtezhengzhi = MathHUtils.juzhengtezhengzhi(a);
//		Arrays.sort(juzhengtezhengzhi);
		System.out.println("特征值：");
		for (int i = 0; i < juzhengtezhengzhi.length; i++) {
			System.out.println(juzhengtezhengzhi[i]);
		}
		//获取重根情况
		Map<Integer, Integer> weizhi_dijichonggen = MatrixUtils.weizhi_dijichonggen(juzhengtezhengzhi);
		
		if (!weizhi_dijichonggen.isEmpty()) {
			throw new RuntimeException("暂时不支持处理重根的情况");
		}
		
		
		
		
		double[][] tezhen_di = new double[juzhengtezhengzhi.length][2];
		
		for (int i = 0; i < tezhen_di.length; i++) {
			tezhen_di[i][0] = 1;
			tezhen_di[i][1] = -juzhengtezhengzhi[i];
		}
		
		
		System.out.println("初始化根据特征值得出来的底");
		//如果存在重根，这一步要额外处理
		
		
		
		
		double[][] tezhen_zhi = new double[juzhengtezhengzhi.length][];
		for (int i = 0; i < tezhen_di.length; i++) {
			
			tezhen_zhi[i] = jisuan(tezhen_di,i);
			
		}
		
		tezhen_zhi = MathHUtils.zhuanzhi(tezhen_zhi);//转置，用来求解多元一次方程组的解
		
		MathHUtils.print(tezhen_zhi);

		System.out.println("一个中间矩阵，分解多项式分式的，这个矩阵存的是分子实数部分=================================");
		double[][] chigua = new double[a.length][a.length];
		for (int i = 0; i < chigua.length; i++) {
			chigua[i][i] = -a[a.length-1-i][a.length-1-i];
		}
		for (int i = 0; i < chigua.length; i++) {
			for (int j = 0; j < chigua[i].length; j++) {
				if (i!=j) {
					chigua[i][j] = a[i][j];

				}
			}
		}
		
		MathHUtils.print(chigua);

		
		//对于矩阵的每个格子里面的向量参数值进行计算确认
		double[][][] et_xiangliang = new double[chigua.length][chigua.length][];
		
		for (int i = 0; i < et_xiangliang.length; i++) {
			for (int j = 0; j < et_xiangliang[i].length; j++) {
				if (i==j) {
					double[] b = {1,chigua[i][j]};
					double[] duoyuanyici = MathUtils.duoyuanyici(tezhen_zhi, b);
					et_xiangliang[i][j] = duoyuanyici;
					
				}else {
					double[] b = {0,chigua[i][j]};
					double[] duoyuanyici = MathUtils.duoyuanyici(tezhen_zhi, b);

					et_xiangliang[i][j] = duoyuanyici;

					
				}
				
			}
		}
		
		System.out.println(".........................");
		for (int i = 0; i < et_xiangliang.length; i++) {
			for (int j = 0; j < et_xiangliang[i].length; j++) {
				
				for (int k = 0; k < et_xiangliang[i][j].length; k++) {
					System.out.print(et_xiangliang[i][j][k]+"   ");
				}
				
				System.out.print("  ,,,  ");
			}
			System.out.println();
		}
		
		
		

		return create_ztzym(et_xiangliang,juzhengtezhengzhi);
	}

	
	/**
	 * 	生成一个状态转移矩阵对象
	 * @param et_xiangliang
	 * @param tezhengzhi
	 * @return
	 */
	private static ZhuangTai_ZhuanYi_Matrix create_ztzym(double[][][] et_xiangliang,final double[] tezhengzhi) {
		ZhuangTai_ZhuanYi_Matrix asa = new ZhuangTai_ZhuanYi_Matrix();
		
		HanShu[][] matrix = new HanShu[et_xiangliang.length][et_xiangliang.length];
		
		for (int i = 0; i < et_xiangliang.length; i++) {
			for (int j = 0; j < et_xiangliang[i].length; j++) {
				final double[] sss = et_xiangliang[i][j];
				
				matrix[i][j] = new HanShu() {
					
					@Override
					public double hanshu(double t, double x) {
						// TODO Auto-generated method stub
						return 0;
					}
					
					@Override
					public double hanshu(double x) {
						// TODO Auto-generated method stub

						double result = 0;
						for (int k = 0; k < sss.length; k++) {
							result += sss[k]*Math.exp(tezhengzhi[k]*x);
						}
						
						
						return result;
					}
				};
			}
		}
		
		asa.setMatrix(matrix);

		
		return asa;
		
	}

	
	
	
	
	/**
	 * 	多项式相乘
	 * @param tezhen_di
	 * @param i
	 * @return
	 */
	private static double[] jisuan(double[][] tezhen_di, int i) {
		// TODO Auto-generated method stub
//		double[] zhi = null;
		
		double[][] asa = new double[tezhen_di.length-1][];
		for (int j = 0; j < tezhen_di.length; j++) {
			if (j<i) {
				asa[j] = tezhen_di[j];

			}else if(j>i){
				asa[j-1] = tezhen_di[j];
			}
			
		}
		double[] zhi = asa[0];
		for (int j = 1; j < asa.length; j++) {
			zhi = dress(zhi,asa[j]);
		}
		
		
		return zhi;
	}
	
	/**
	 * 	多项式相乘，这个方法会自动补齐长度不同的两个多项式
	 * @param a
	 * @param b
	 * @return
	 */
	private static double[] dress(double[] a,double[] b) {
		
		
		if (a.length>b.length) {
			double [] jisuan_b = new double[a.length];
			for (int i = b.length; i < jisuan_b.length; i++) {
				jisuan_b[i] = b[i-b.length];
			}
			return NTT2My.C(a, jisuan_b);

		}else if (a.length<b.length) {
			
			double [] jisuan_a = new double[b.length];
			for (int i = 0; i < jisuan_a.length; i++) {
					jisuan_a[i] = a[i-a.length];
			}
			return NTT2My.C(jisuan_a, b);

		}
		
		
		return NTT2My.C(a, b);

	}
	
	
	
	/**
	 * Cayley-Hamilton定理
	 * 	求解状态转移矩阵
	 */
	public static double[][][] Hamilton_eAt(double[][] a,double[] juzhengtezhengzhi) {
		
		
//		for (int i = 0; i < juzhengtezhengzhi.length/2; i++) {
//			double d = juzhengtezhengzhi[i];
//			juzhengtezhengzhi[i] = juzhengtezhengzhi[juzhengtezhengzhi.length-1-i];
//			juzhengtezhengzhi[juzhengtezhengzhi.length-1-i] = d;
//			System.out.println("1dw");
//		}
		
		
		System.out.println("特征值：");
		for (int i = 0; i < juzhengtezhengzhi.length; i++) {
			System.out.println(juzhengtezhengzhi[i]);
		}
		//获取重根情况
//		Map<Integer, Integer> weizhi_dijichonggen = MatrixUtils.weizhi_dijichonggen(juzhengtezhengzhi);
//		
//		if (!weizhi_dijichonggen.isEmpty()) {
//			throw new RuntimeException("暂时不支持处理重根的情况");
//		}
		
		
		//初始化要计算的矩阵.		我猜测吧这一段即asa的结果直接换成范德蒙(Vandemone)矩阵应该就能求重根的情况了
//		double[][] asa = new double[a.length][a.length];		
//		
//		for (int i = 0; i < asa[0].length; i++) {
//			asa[0][i] = 1;
//		}
//		for (int i = 1; i < asa.length; i++) {//这种方式不用每次重新求指数函数，这次利用了上一次的计算结果，性能稍微好一点
//			for (int j = 0; j < asa[i].length; j++) {
//				asa[i][j] = asa[i-1][j]*juzhengtezhengzhi[j];
//			}
//		}
		double[][] asa = MatrixUtils.Vandemone(a);
		asa = MathHUtils.zhuanzhi(asa);
		System.out.println("生产矩阵：");
		MathHUtils.print(asa);
		
		
		double[][][] last = new double[a.length][a.length][a.length];
		
		last[0]=MathHUtils.getI(a.length);

		for (int i = 1; i < last.length; i++) {
			
			last[i] = MathHUtils.chenfa(last[i-1], a);
		}
		System.out.println("生产矩阵的矩阵，即最后一行："+(last.length-1));
		MathHUtils.print(last[last.length-1]);

		
		
		
		
		//一个矩阵剔除掉某行某列，生成出一个新的矩阵
//		int remove_i = 0;
//		int remove_j = 0;
//		
//		double daishuyuzixiang = Ni.daishuyuzixiang(asa, remove_i, remove_j);
//	
//		System.out.println("代数余子式：");
//		System.out.println(daishuyuzixiang);
		
		
//		double[][] first_one = new double[a.length][];
//		
//		double[][] asb = new double[][];
//		for (int i = 0; i < first_one.length; i++) {
//			for (int j = 0; j < first_one.length; j++) {
//				
//			}
//		}
		
		System.out.println("代数余子式：");
		
		double[][][] et = new double[juzhengtezhengzhi.length][juzhengtezhengzhi.length][juzhengtezhengzhi.length];
		for (int i = 0; i < juzhengtezhengzhi.length; i++) {
			
			double[][] pre = new double[a.length][a.length];
			for (int j = 0; j < last.length; j++) {
				int remove_i = i;
				int remove_j = j;
				double daishuyuzixiang = Ni.daishuyuzixiang(asa, remove_i, remove_j);
				daishuyuzixiang = ((remove_i+remove_j)%2==1?-1:1) *daishuyuzixiang;
				
				double[][] ds = last[j];
				
				double[][] chenfa = MathHUtils.chenfa(ds, daishuyuzixiang);
				pre = MathHUtils.jiafa(pre, chenfa);
				
				

			}
			et[i] = pre;
			
		}
		
		
		
		
		double hangleishivalue = Ni.hangleishivalue(asa);
		
		
		for (int i = 0; i < et.length; i++) {
			et[i] = MathHUtils.chenfa(et[i], 1/hangleishivalue);
			System.out.println(juzhengtezhengzhi[i]);
			MathHUtils.print(et[i]);
			System.out.println("-------------");
		}
		
		
		return et;
		
		
	}
	
	
	
	
	/**
	 * 通过使用特征值，特征向量的方式来求状态转移矩阵
	 * 不支持重根
	 * @param a
	 * @return
	 * @throws Exception 
	 */
	public static ZhuangTai_ZhuanYi_Matrix create_zhuangtaizhuanyi_matrix_eAt_bytezhengzhi(double[][] a) throws Exception {
		double[] juzhengtezhengzhi = MathHUtils.juzhengtezhengzhi(a);
//		Arrays.sort(juzhengtezhengzhi);
		
		MathHUtils.beauty(juzhengtezhengzhi, 1);
//		System.out.println("特征值：");
//		for (int i = 0; i < juzhengtezhengzhi.length; i++) {
//			System.out.println(juzhengtezhengzhi[i]);
//		}
		//获取重根情况
		Map<Integer, Integer> weizhi_dijichonggen = MatrixUtils.weizhi_dijichonggen(juzhengtezhengzhi);
		
		if (!weizhi_dijichonggen.isEmpty()) {
			
			double[][] juzhengtezhengxiangliang = MathHUtils.juzhengtezhengxiangliang(a, juzhengtezhengzhi);
			System.out.println("重根情况下的特征向量");

			MathHUtils.print(juzhengtezhengxiangliang);
			
			
			
			
			throw new RuntimeException("暂时不支持处理重根的情况");
		}
		
		
		double[][] juzhengtezhengxiangliang = MathHUtils.juzhengtezhengxiangliang(a,juzhengtezhengzhi);
		
		juzhengtezhengxiangliang = MathHUtils.zhuanzhi(juzhengtezhengxiangliang);
		
		System.out.println("计算特征向量");
		MathHUtils.print(juzhengtezhengxiangliang);
		
		double[][] juzhengtezhengxiangliang_ni = MathHUtils.juzhengni(juzhengtezhengxiangliang);

		double[][][] et_xiangliang = new double[juzhengtezhengzhi.length][][];
		System.out.println("------------------------------------");
		
		for (int i = 0; i < juzhengtezhengzhi.length; i++) {
			double[][] canshu1 = MathHUtils.get0_1(juzhengtezhengxiangliang.length, i, i);
			et_xiangliang[i] = MathHUtils.chenfa(juzhengtezhengxiangliang,canshu1);
		}
		MathHUtils.print(et_xiangliang[0]);
		System.out.println("....");
		
		for (int i = 0; i < et_xiangliang.length; i++) {
			et_xiangliang[i] = MathHUtils.chenfa(et_xiangliang[i], juzhengtezhengxiangliang_ni);
		}
		
		MathHUtils.print(et_xiangliang[0]);
		
		return create_ztzym(et_xiangliang,juzhengtezhengzhi);
	
	
	}
	
	
	
	
	
	
	
	
	
	
}
